#pragma once
#include <iostream>
#include <queue>
#include <condition_variable>

template <class T>

class ShareQueue {
public:
	ShareQueue(int size=5,bool block=true);
	~ShareQueue();
	bool hasData();
	bool put(T data);
	T get();
private:
	std ::queue<T> queue;
	std::mutex mutex;
	std::condition_variable cond_variable;
	bool canRead = true;
	int count=0;
	int queueSize = 0;
	bool block = true;
};

template<class T>
inline ShareQueue<T>::ShareQueue(int size,bool block)
{
	this->count = 0;
	this->queueSize = size;
	this->block = block;
}

template<class T>
inline ShareQueue<T>::~ShareQueue()
{

}

template<class T>
inline bool ShareQueue<T>::hasData()
{
	while (!this->canRead) {

	}
	return !this->queue.empty();
}

template<class T>
inline bool ShareQueue<T>::put(T data)
{
	if ((this->block)&&(this->count >= this->queueSize)) {
		if (this->mutex.try_lock()) {
			this->canRead = false;
		}
		this->queue.pop();
		this->count--;
		this->canRead = true;
		this->mutex.unlock();
	}
	this->queue.push(data);
	this->count++;
	return true;
}

template<class T>
inline T ShareQueue<T>::get()
{
	T data;
	while (!this->canRead) {
	}
	if (!queue.empty()) {
		data = queue.front();
		queue.pop();
		this->count--;
	}
	return data;
}
